package com.example.web.service.server.springbootwebserviceserver.controller;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.http.webservice.SoapClient;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.web.service.server.springbootwebserviceserver.server.dto.TestBean;
import com.example.web.service.server.springbootwebserviceserver.po.WebServiceInfo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPException;
import java.util.Objects;

/**
 * MockController.
 *
 * @author <a href='mailto:likeguo@apache.com'> likeguo </a>
 */
@RestController
@RequestMapping("convert")
public class WebServiceApiConvertRestController {
    
    
    @PostMapping("/")
    public Object convert(@RequestBody WebServiceInfo info) {
        try {
            // 新建客户端
            SoapClient client = SoapClient.create(info.getServiceUrl())
                    .setMethod("web:" + info.getMethod(), info.getNamespace());
            // 构建转换参数
            addParams(info, client);
            
            Console.log("web service 服务代理 send:");
            Console.log("web Service address: " + info.getServiceUrl());
            Console.log(client.getMsgStr(true));
            // 发起WebService调用
            final String send = client.send(false);
            Console.log("web Service 响应体（xml）：");
            final Document document = XmlUtil.parseXml(send);
            Console.log(XmlUtil.format(document));
            final Node returnNode = find(document, "return");
            if (Objects.nonNull(returnNode)) {
                final String res = JSONUtil.toJsonStr(XmlUtil.xmlToMap(returnNode));
                Console.log("转发给客户端（Json）:");
                Console.log(JSONUtil.formatJsonStr(res));
                return JSONUtil.parseObj(res);
            }
            return "nod return result";
        } catch (Exception e) {
            e.printStackTrace();
            return "error:" + e.getMessage();
        }
    }
    
    private void addParams(WebServiceInfo info, SoapClient client) {
        info.getParams().forEach((k, v) -> {
            final JSONObject json = JSONUtil.parseObj(v);
            try {
                final SOAPElement p = client.getMethodEle().addChildElement(k, "web");
                json.forEach(node -> {
                    try {
                        p.addChildElement(node.getKey()).setValue(Objects.toString(node.getValue()));
                    } catch (SOAPException e) {
                        throw new RuntimeException(e);
                    }
                });
            } catch (SOAPException e) {
                throw new RuntimeException(e);
            }
        });
    }
    
    @GetMapping("/4")
    public String mock4(TestBean bean) {
        try {
            // 新建客户端
            SoapClient client = SoapClient.create("http://localhost:8080/soap/ws/api?wsdl")
                    // 设置要请求的方法，此接口方法前缀为web，传入对应的命名空间
                    .setMethod("web:getTest2", "http://server.springbootwebserviceserver.server.service.web.example.com/");
//                    // 设置参数，此处自动添加方法的前缀：web
//                    .setParam("test2", XmlUtil.toStr(XmlUtil.beanToXml(bean)));
//
            final SOAPElement test2 = client.getMethodEle().addChildElement("test2", "web");
            final String p = JSONUtil.toJsonStr(bean);
            
            test2.appendChild(XmlUtil.parseXml(JSONUtil.toXmlStr(JSONUtil.parseObj(bean))).getDocumentElement());
            
            Console.log("send:");
            Console.log(client.getMsgStr(true));
            // 返回内容为XML字符串，可以配合XmlUtil解析这个响应
            final String send = client.send(false);
            Console.log("return:");
            final Document document = XmlUtil.parseXml(send);
            Console.log(XmlUtil.format(document));
            final Node returnNode = find(document, "return");
            final String res = JSONUtil.toJsonStr(XmlUtil.xmlToMap(returnNode));
            Console.log(res);
            return res;
        } catch (Exception e) {
            e.printStackTrace();
            return "error:" + e.getMessage();
        }
    }
    
    private Node find(Node node, String name) {
        if (Objects.equals(node.getNodeName(), name)) {
            return node;
        }
        final NodeList childNodes = node.getChildNodes();
        for (int i = 0; i < childNodes.getLength(); i++) {
            final Node item = childNodes.item(i);
            if (item.hasChildNodes()) {
                return find(node.getFirstChild(), name);
            }
        }
        return null;
    }
}
